package com.boot.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.boot.common.constant.GlobalVar;
import com.boot.common.constant.MessageConstant;
import com.boot.common.constant.RedisConstant;
import com.boot.common.result.Result;
import com.boot.system.entity.SysModule;
import com.boot.system.entity.SysUser;
import com.boot.system.mapper.ModuleMapper;
import com.boot.system.service.DatabaseService;
import com.boot.system.service.ModuleService;
import com.boot.util.CommUtil;
import com.boot.util.ConvertUtil;
import com.boot.util.RedisUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service("moduleService")
public class ModuleServiceImpl extends ServiceImpl<ModuleMapper, SysModule> implements ModuleService {

    private final RedisUtil redisUtil;

    private final DatabaseService databaseService;

    /**
     * 系统启动完成后，加载模块列表缓存
     */
    @PostConstruct
    public void initModule() {
        QueryWrapper query = QueryWrapper.create().from(SysModule.class);
        List<SysModule> list = this.list(query);
        for (SysModule sysModule : list) {
            String key = StrUtil.format(RedisConstant.Module.INFO, sysModule.getId(), sysModule.getMid());
            redisUtil.set(key, sysModule);
        }
        log.info("模块列表加载完成！");
    }

    @Override
    public Page<SysModule> getModulePage(Map<String, Object> queryParam) {
        // 基础参数
        int pageNum = (int) queryParam.getOrDefault("pageNum", 1);
        int pageSize = (int) queryParam.getOrDefault("pageSize", 10);
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysModule.class);
        query.and(q -> q.and(SysModule::getName).like(queryParam.get("keywords"))
                        .or(SysModule::getMid).like(queryParam.get("keywords")),
                ObjectUtil.isNotEmpty(queryParam.get("keywords")));
        query.orderBy((String) queryParam.getOrDefault("orderBy", "update_time desc, id desc"));
        return this.page(new Page<>(pageNum, pageSize), query);
    }

    @Override
    public Result<?> getModuleInfo(String mid) {
        SysModule sysModule = this.getCache(mid);
        if (sysModule != null) {
            // 当前登录用户
            SysUser loginUser = SecurityUtil.getUserInfo();
            // 根据角色判断是否有权限
            if (ObjectUtil.isNotEmpty(sysModule.getRoles()) && !"super".equals(SecurityUtil.getUsername())) {
                if (!CommUtil.compareArrays(sysModule.getRoleArr(), loginUser.getRoleArr())) {
                    return Result.error(MessageConstant.PERMISSION_DENIED);
                }
            }
            return Result.success(sysModule);
        }
        return Result.error(MessageConstant.PERMISSION_DENIED);
    }

    @Override
    public Result<?> addModule(Map<String, Object> dataParam) {
        //判断是否已存在
        if (dataParam.get("mid") != null) {
            SysModule sysModuleTemp = this.mapper.selectByMid((String) dataParam.get("mid"));
            if (sysModuleTemp != null) {
                //已存在
                return Result.error(MessageConstant.MODULE_EXIST);
            }
        }
        SysModule sysModule = ConvertUtil.mapToClass(dataParam, SysModule.class);
        if (dataParam.get("apiJson") != null) {
            sysModule.setApiJson(JSONUtil.toJsonStr(dataParam.get("apiJson")));
        }
        if (dataParam.get("btnJson") != null) {
            sysModule.setBtnJson(JSONUtil.toJsonStr(dataParam.get("btnJson")));
        }
        if (dataParam.get("tableJson") != null) {
            sysModule.setTableJson(JSONUtil.toJsonStr(dataParam.get("tableJson")));
        }
        sysModule.setCreateBy(SecurityUtil.getUid());
        sysModule.setCreateTime(GlobalVar.systemTime);
        sysModule.setUpdateBy(SecurityUtil.getUid());
        sysModule.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.save(sysModule);
        if (result) {
            // 更新缓存列表
            this.setCache(sysModule.getId());
            // 新表创建
            databaseService.createTable(sysModule);
        }
        return Result.success(result);
    }

    @Override
    public Result<?> updateModule(Map<String, Object> dataParam) {
        //查询原数据
        SysModule oldSysModule = this.getById(Long.valueOf(dataParam.get("id").toString()));
        //判断是否可以修改
        if (dataParam.get("mid") != null && !dataParam.get("mid").equals(oldSysModule.getMid())) {
            SysModule sysModuleTemp = this.mapper.selectByMid((String) dataParam.get("mid"));
            if (sysModuleTemp != null) {
                //已存在
                return Result.error(MessageConstant.MODULE_EXIST);
            }
        }
        SysModule sysModule = ConvertUtil.mapToClass(dataParam, SysModule.class);
        if (dataParam.get("apiJson") != null) {
            sysModule.setApiJson(JSONUtil.toJsonStr(dataParam.get("apiJson")));
        }
        if (dataParam.get("btnJson") != null) {
            sysModule.setBtnJson(JSONUtil.toJsonStr(dataParam.get("btnJson")));
        }
        if (dataParam.get("tableJson") != null) {
            sysModule.setTableJson(JSONUtil.toJsonStr(dataParam.get("tableJson")));
        }
        sysModule.setUpdateBy(SecurityUtil.getUid());
        sysModule.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.updateById(sysModule);
        if (result) {
            // 更新缓存列表
            this.deleteCache(Collections.singletonList(sysModule.getId()));
            this.setCache(sysModule.getId());
            // 修改表结构
            databaseService.updateTable(sysModule);
        }
        return Result.success(result);
    }

    @Override
    public boolean deleteModule(String ids) {
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        //先删除缓存
        this.deleteCache(idList);
        //数据库-逻辑删除
        return this.removeByIds(idList);
    }

    @Override
    public SysModule getCache(String mid) {
        String prefix = StrUtil.format(RedisConstant.Module.INFO, "*", mid);
        //获取真实的缓存Key
        String key = null;
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String item : keys) {
            key = item;
        }
        if (key != null) {
            return (SysModule) redisUtil.get(key);
        }
        return null;
    }

    @Override
    public void setCache(Long id) {
        SysModule sysModule = this.getById(id);
        if (sysModule != null) {
            String key = StrUtil.format(RedisConstant.Module.INFO, sysModule.getId(), sysModule.getMid());
            redisUtil.set(key, sysModule);
        }
    }

    @Override
    public void deleteCache(List<Long> ids) {
        for (Long id : ids) {
            String prefix = StrUtil.format(RedisConstant.Module.INFO, id, "*");
            //获取真实的缓存Key
            String key = null;
            Set<String> keys = redisUtil.getKeys(prefix);
            for (String item : keys) {
                key = item;
            }
            if (key != null) {
                //删除
                redisUtil.delete(key);
            }
        }
    }
}
